/**
 * html字符串转换成uNode节点
 * @file
 * @module UE
 * @since 1.2.6.1
 */

/**
 * UEditor公用空间，UEditor所有的功能都挂载在该空间下
 * @unfile
 * @module UE
 */

/**
 * html字符串转换成uNode节点的静态方法
 * @method htmlparser
 * @param { String } htmlstr 要转换的html代码
 * @param { Boolean } ignoreBlank 若设置为true，转换的时候忽略\n\r\t等空白字符
 * @return { uNode } 给定的html片段转换形成的uNode对象
 * @example
 * ```javascript
 * var root = UE.htmlparser('<p><b>htmlparser</b></p>', true);
 * ```
 */

var htmlparser = (UE.htmlparser = function (htmlstr, ignoreBlank) {
    //todo 原来的方式  [^"'<>\/] 有\/就不能配对上 <TD vAlign=top background=../AAA.JPG> 这样的标签了
    //先去掉了，加上的原因忘了，这里先记录
    //var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/<>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g,
    //以上的正则表达式无法匹配:<div style="text-align:center;font-family:" font-size:14px;"=""><img src="http://hs-album.oss.aliyuncs.com/static/27/78/35/image/20161206/20161206174331_41105.gif" alt="" /><br /></div>
    //修改为如下正则表达式:
    var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/g,
        re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g;

    //ie下取得的html可能会有\n存在，要去掉，在处理replace(/[\t\r\n]*/g,'');代码高量的\n不能去除
    var allowEmptyTags = {
        b: 1,
        code: 1,
        i: 1,
        u: 1,
        strike: 1,
        s: 1,
        tt: 1,
        strong: 1,
        q: 1,
        samp: 1,
        em: 1,
        span: 1,
        sub: 1,
        img: 1,
        sup: 1,
        font: 1,
        big: 1,
        small: 1,
        iframe: 1,
        a: 1,
        br: 1,
        pre: 1
    };
    htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, "g"), "");
    if (!ignoreBlank) {
        htmlstr = htmlstr.replace(
            new RegExp(
                "[\\r\\t\\n" +
                (ignoreBlank ? "" : " ") +
                "]*</?(\\w+)\\s*(?:[^>]*)>[\\r\\t\\n" +
                (ignoreBlank ? "" : " ") +
                "]*",
                "g"
            ),
            function (a, b) {
                //br暂时单独处理
                if (b && allowEmptyTags[b.toLowerCase()]) {
                    return a.replace(/(^[\n\r]+)|([\n\r]+$)/g, "");
                }
                return a
                    .replace(new RegExp("^[\\r\\n" + (ignoreBlank ? "" : " ") + "]+"), "")
                    .replace(
                        new RegExp("[\\r\\n" + (ignoreBlank ? "" : " ") + "]+$"),
                        ""
                    );
            }
        );
    }

    var notTransAttrs = {
        href: 1,
        src: 1
    };

    var uNode = UE.uNode,
        needParentNode = {
            td: "tr",
            tr: ["tbody", "thead", "tfoot"],
            tbody: "table",
            th: "tr",
            thead: "table",
            tfoot: "table",
            caption: "table",
            li: ["ul", "ol"],
            dt: "dl",
            dd: "dl",
            option: "select"
        },
        needChild = {
            ol: "li",
            ul: "li"
        };

    function text(parent, data) {
        if (needChild[parent.tagName]) {
            var tmpNode = uNode.createElement(needChild[parent.tagName]);
            parent.appendChild(tmpNode);
            tmpNode.appendChild(uNode.createText(data));
            parent = tmpNode;
        } else {
            parent.appendChild(uNode.createText(data));
        }
    }

    function element(parent, tagName, htmlattr) {
        var needParentTag;
        if ((needParentTag = needParentNode[tagName])) {
            var tmpParent = parent,
                hasParent;
            while (tmpParent.type != "root") {
                if (
                    utils.isArray(needParentTag)
                        ? utils.indexOf(needParentTag, tmpParent.tagName) != -1
                        : needParentTag == tmpParent.tagName
                ) {
                    parent = tmpParent;
                    hasParent = true;
                    break;
                }
                tmpParent = tmpParent.parentNode;
            }
            if (!hasParent) {
                parent = element(
                    parent,
                    utils.isArray(needParentTag) ? needParentTag[0] : needParentTag
                );
            }
        }
        //按dtd处理嵌套
        //        if(parent.type != 'root' && !dtd[parent.tagName][tagName])
        //            parent = parent.parentNode;
        var elm = new uNode({
            parentNode: parent,
            type: "element",
            tagName: tagName.toLowerCase(),
            //是自闭合的处理一下
            children: dtd.$empty[tagName] ? null : []
        });
        //如果属性存在，处理属性
        if (htmlattr) {
            var attrs = {},
                match;
            while ((match = re_attr.exec(htmlattr))) {
                attrs[match[1].toLowerCase()] = notTransAttrs[match[1].toLowerCase()]
                    ? match[2] || match[3] || match[4]
                    : utils.unhtml(match[2] || match[3] || match[4]);
            }
            elm.attrs = attrs;
        }
        //trace:3970
        //        //如果parent下不能放elm
        //        if(dtd.$inline[parent.tagName] && dtd.$block[elm.tagName] && !dtd[parent.tagName][elm.tagName]){
        //            parent = parent.parentNode;
        //            elm.parentNode = parent;
        //        }
        parent.children.push(elm);
        //如果是自闭合节点返回父亲节点
        return dtd.$empty[tagName] ? parent : elm;
    }

    function comment(parent, data) {
        parent.children.push(
            new uNode({
                type: "comment",
                data: data,
                parentNode: parent
            })
        );
    }

    var match,
        currentIndex = 0,
        nextIndex = 0;
    //设置根节点
    var root = new uNode({
        type: "root",
        children: []
    });
    var currentParent = root;

    while ((match = re_tag.exec(htmlstr))) {
        currentIndex = match.index;
        try {
            if (currentIndex > nextIndex) {
                //text node
                text(currentParent, htmlstr.slice(nextIndex, currentIndex));
            }
            if (match[3]) {
                if (dtd.$cdata[currentParent.tagName]) {
                    text(currentParent, match[0]);
                } else {
                    //start tag
                    currentParent = element(
                        currentParent,
                        match[3].toLowerCase(),
                        match[4]
                    );
                }
            } else if (match[1]) {
                if (currentParent.type != "root") {
                    if (dtd.$cdata[currentParent.tagName] && !dtd.$cdata[match[1]]) {
                        text(currentParent, match[0]);
                    } else {
                        var tmpParent = currentParent;
                        while (
                            currentParent.type == "element" &&
                            currentParent.tagName != match[1].toLowerCase()
                            ) {
                            currentParent = currentParent.parentNode;
                            if (currentParent.type == "root") {
                                currentParent = tmpParent;
                                throw "break";
                            }
                        }
                        //end tag
                        currentParent = currentParent.parentNode;
                    }
                }
            } else if (match[2]) {
                //comment
                comment(currentParent, match[2]);
            }
        } catch (e) {
        }

        nextIndex = re_tag.lastIndex;
    }
    //如果结束是文本，就有可能丢掉，所以这里手动判断一下
    //例如 <li>sdfsdfsdf<li>sdfsdfsdfsdf
    if (nextIndex < htmlstr.length) {
        text(currentParent, htmlstr.slice(nextIndex));
    }
    return root;
});
